package com.socket.nio.nio.chat.example.client;

import com.socket.nio.nio.chat.example.handler.ChatClientHandler;
import com.socket.nio.nio.chat.example.protocol.ChatMessage;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * @author Hexudong
 * @date 2025/5/12
 */
@Slf4j
public class ChatClient {
  private final String host;
  private final int port;
  private Channel channel;

  public ChatClient(String host, int port) {
    this.host = host;
    this.port = port;
  }

  public void run() throws Exception {
    EventLoopGroup group = new NioEventLoopGroup();
    try {
      Bootstrap b = new Bootstrap();
      b.group(group)
          .channel(NioSocketChannel.class)
          .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) {
              ch.pipeline().addLast(
                  new ProtobufVarint32FrameDecoder(),
                  new ProtobufDecoder(ChatMessage.Msg.getDefaultInstance()),
                  new ProtobufVarint32LengthFieldPrepender(),
                  new ProtobufEncoder(),
                  new ChatClientHandler());
            }
          });

      ChannelFuture f = b.connect(host, port).sync();
      channel = f.channel();

      // 处理用户输入
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      while (true) {
        String line = in.readLine();
        // 解析命令并构建消息
        // 示例命令：
        // /login username
        // /msg target message
        // /create groupname
        // /join groupname
        // /groupmsg groupname message
        if (line.startsWith("/")) {
          handleCommand(line);
        } else if (line.startsWith("q")) {
          break;
        } else {
          System.out.println("Unknown command");
        }
      }
    } finally {
      group.shutdownGracefully();
    }
  }

  private void handleCommand(String command) {
    String[] parts = command.split(" ", 4);
    switch (parts[0]) {
      case "/login": // /login user1
        sendLogin(parts[1]);
        break;
      case "/msg":// /msg user1 user2 msg
        sendPrivateMessage(parts[1], parts[2], parts[3]);
        break;
      case "/create": // /create user1 groupName1
        createGroup(parts[1], parts[2]);
        break;
      case "/join": // /join user1 groupName1
        joinGroup(parts[1], parts[2]);
        break;
      case "/groupmsg":// /groupmsg user1 groupName1 msg
        sendGroupMessage(parts[1], parts[2], parts[3]);
        break;
    }
  }

  /**
   * 用户登录
   *
   * @param username 用户名
   */
  private void sendLogin(String username) {
    ChatMessage.Msg msg = ChatMessage.Msg.newBuilder()
        .setType(ChatMessage.Msg.MsgType.LOGIN)
        .setUsername(username)
        .build();
    channel.writeAndFlush(msg);
  }

  /**
   * 发送私聊消息
   * @param currentUser 发送用户名
   * @param targetUser 接收方用户名
   * @param message 消息内容
   */
  private void sendPrivateMessage(String currentUser, String targetUser, String message) {
    if (channel == null || !channel.isActive()) {
      System.err.println("Connection not established");
      return;
    }
    ChatMessage.Msg msg = ChatMessage.Msg.newBuilder()
        .setType(ChatMessage.Msg.MsgType.TEXT)
        .setUsername(currentUser)
        .setTarget(targetUser)
        .setContent(message)
        .build();

    channel.writeAndFlush(msg);
    System.out.println(currentUser + " send message to " + targetUser + ", and message content is: " + message);
  }

  /**
   * 创建群组
   * @param currentUser 发送用户名
   * @param groupName 群组名称
   */
  private void createGroup(String currentUser, String groupName) {
    if (channel == null || !channel.isActive()) {
      System.err.println("Connection not established");
      return;
    }

    ChatMessage.Msg msg = ChatMessage.Msg.newBuilder()
        .setType(ChatMessage.Msg.MsgType.CREATE_GROUP)
        .setUsername(currentUser)
        .setGroupName(groupName)
        .build();

    channel.writeAndFlush(msg);
    System.out.println("[System] Creating group: " + groupName);
  }

  /**
   * 加入群组
   * @param currentUser 发送用户名
   * @param groupName 群组名称
   */
  private void joinGroup(String currentUser, String groupName) {
    if (channel == null || !channel.isActive()) {
      System.err.println("Connection not established");
      return;
    }

    ChatMessage.Msg msg = ChatMessage.Msg.newBuilder()
        .setType(ChatMessage.Msg.MsgType.JOIN_GROUP)
        .setUsername(currentUser)
        .setGroupName(groupName)
        .build();

    channel.writeAndFlush(msg);
    System.out.println("[System] " + currentUser + " Joining group: " + groupName);
  }

  /**
   * 发送群组消息
   * @param currentUser 发送用户名
   * @param groupName 群组名称
   * @param message 消息内容
   */
  private void sendGroupMessage(String currentUser, String groupName, String message) {
    if (channel == null || !channel.isActive()) {
      System.err.println("Connection not established");
      return;
    }

    ChatMessage.Msg msg = ChatMessage.Msg.newBuilder()
        .setType(ChatMessage.Msg.MsgType.GROUP_MSG)
        .setUsername(currentUser)
        .setGroupName(groupName)
        .setContent(message)
        .build();

    channel.writeAndFlush(msg);
    System.out.println("[You @ " + groupName + "] " + message);
  }

  public static void main(String[] args) throws Exception {
    new ChatClient("localhost", 8082).run();
  }
}
